// Learn TypeScript:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] http://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

@ccclass
export default class DragView extends cc.Component {

    private _touchMoved = false;
    private _canMove = true;

    onEnable() {
        if (!CC_EDITOR) {
            this._registerEvent();
        }
    }
    onDisable () {
        if (!CC_EDITOR) {
            this._unregisterEvent();
        }
    }

    _registerEvent () {
        this.node.on(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this, true);
        this.node.on(cc.Node.EventType.TOUCH_MOVE, this._onTouchMoved, this, true);
        this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this, true);
        this.node.on(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancelled, this, true);
    }

    _unregisterEvent () {
        this.node.off(cc.Node.EventType.TOUCH_START, this._onTouchBegan, this, true);
        this.node.off(cc.Node.EventType.TOUCH_MOVE, this._onTouchMoved, this, true);
        this.node.off(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this, true);
        this.node.off(cc.Node.EventType.TOUCH_CANCEL, this._onTouchCancelled, this, true);
    }

    _stopPropagationIfTargetIsMe (event) {
        if (event.eventPhase === cc.Event.AT_TARGET && event.target === this.node) {
            event.stopPropagation();
        }
    }

    _onTouchBegan (event, captureListeners) {
        this._touchMoved = false;
        this._canMove = true;
        this._stopPropagationIfTargetIsMe(event);
    }

    _onTouchMoved (event, captureListeners) {
        let touch = event.touch;
        let deltaMove = touch.getLocation().sub(touch.getStartLocation());

        //FIXME: touch move delta should be calculated by DPI.
        if (deltaMove.mag() > 7) {
            this._canMove = false;
            if (!this._touchMoved && event.target !== this.node) {
                // Simulate touch cancel for target node
                let cancelEvent = new cc.Event.EventTouch(event.getTouches(), event.bubbles);
                cancelEvent.type = cc.Node.EventType.TOUCH_CANCEL;
                cancelEvent.touch = event.touch;
                event.target.dispatchEvent(cancelEvent);
                this._touchMoved = true;

                if (!this._canMove) {
                    this.node.emit("onDrag", event.target);
                }
            }
        }
        this._stopPropagationIfTargetIsMe(event);
    }

    _onTouchEnded (event, captureListeners) {
        let touch = event.touch;
        
        if (this._touchMoved) {
            event.stopPropagation();
        } else {
            this._stopPropagationIfTargetIsMe(event);
        }
    }
    
    _onTouchCancelled (event, captureListeners) {
        this._stopPropagationIfTargetIsMe(event);
    }
}
